<script setup lang="ts">
import { onMounted, ref, reactive } from 'vue'
import * as THREE from 'three'
import * as TWEEN from 'tween'
import map_img from '@/assets/images/earth/earth.jpg'
import glow_img from '@/assets/images/earth/glow.png'
import map_wl from '@/assets/images/earth/label.png'
import gradient from '@/assets/images/earth/gradient.png'
import { flyArc } from '../../../Utils/arc'
import { createAnimateLine, getCirclePoints } from '../../../Utils/common'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import {
  CSS2DRenderer,
  CSS2DObject,
} from 'three/examples/jsm/renderers/CSS2DRenderer'

import earthVertex from '../../../shaders/earth/vertex.vs.glsl'
import earthFragment from '../../../shaders/earth/fragment.fs.glsl'

const isLogin = ref(true) // 是否登录

let camera, scene, controls, mesh
let group = new THREE.Group() as any
let radius = isLogin.value === true ? 35 : 80
let fov = 100

const data = reactive({
  mapDom: null,
  renderer: null,
  labelRenderer: null,
  animationType: true, // 地球入场动画
  rotationY: true, // 地球自动旋转
  meshAnimateType: false, // 标记点动画
  lonlat: { x: 0, y: 30, z: 200 },
  countryName: null, // 数据
})
onMounted(() => {
  info()
})
const info = () => {
  infoThree() // 基本配置
  infoBall() // 创建地球
  createStars() // 创建星空
  // createEarthAperture() // 创建地球大气层
  createAnimateCircle() // 创建地球卫星
  earthAperture() // 地球外围贴图
  sweepLight() // 扫光
  infoRender() // 重新渲染
  data.renderer.domElement.addEventListener('click', infoMouse)
  data.labelRenderer.domElement.addEventListener('click', infoMouse)
}
// 基本配置
const mapId = ref(null)
const infoThree = () => {
  // 场景
  scene = new THREE.Scene()
  // 渲染
  data.renderer = new THREE.WebGLRenderer({
    antialias: true,
  })
  data.mapDom = mapId
  data.renderer.setSize(data.mapDom.clientWidth, data.mapDom.clientHeight)
  data.renderer.setClearColor(0x000, 0)
  data.mapDom.appendChild(data.renderer.domElement)

  // 标签渲染
  data.labelRenderer = new CSS2DRenderer()
  data.labelRenderer.setSize(data.mapDom.clientWidth, data.mapDom.clientHeight)
  data.labelRenderer.domElement.style.position = 'absolute'
  data.labelRenderer.domElement.style.top = '0px'
  document.body.appendChild(data.labelRenderer.domElement)

  // 相机
  camera = new THREE.PerspectiveCamera(
    fov,
    data.mapDom.clientWidth / data.mapDom.clientHeight,
    1,
    1000
  )
  // camera.position.set(0, 30, -250) // 设置相机位置 中国
  // camera.lookAt(0, 0, 0) // 设置相机方向(指向的场景对象)
  // 鼠标
  infoOrbitControls()
}

// 重新渲染
const infoRender = () => {
  data.renderer.clear()
  // 地球入场动画
  if (data.animationType) ballAnimation()
  // 地球旋转
  if (data.rotationY) ballRotationY()
  // 标记点动画
  if (data.meshAnimateType) meshAnimate()
  data.renderer.render(scene, camera)
  data.labelRenderer.render(scene, camera)
  requestAnimationFrame(infoRender)
  sweepLightFn() // 扫光
  surround() // 卫星环绕函数
  flyLine() // 飞线运动函数
  TWEEN.update()
}
// 鼠标
const infoOrbitControls = () => {
  controls = new OrbitControls(camera, data.labelRenderer.domElement)
  controls.enableDamping = true // 是否开启阻尼
  controls.enableZoom = isLogin.value === true ? true : false // 是否开启鼠标滚轮缩放
  controls.autoRotate = false // 是否开启自动旋转
  controls.autoRotateSpeed = 30 // 设置自动旋转速度
  controls.enablePan = true // 是否开启右键拖拽
  controls.minDistance = 100 // 设置相机距离原点的最近距离
  controls.maxDistance = 300 // 设置相机距离原点的最远距离
}

// 星空效果
const createStars = () => {
  const vertices = []
  const colors = []
  for (let i = 0; i < 500; i++) {
    const vertex = new THREE.Vector3()
    vertex.x = 800 * Math.random() - 300
    vertex.y = 800 * Math.random() - 300
    vertex.z = 800 * Math.random() - 300
    vertices.push(vertex.x, vertex.y, vertex.z)
    colors.push(new THREE.Color(1, 1, 1))
  }
  const around = new THREE.BufferGeometry()
  around.setAttribute(
    'position',
    new THREE.BufferAttribute(new Float32Array(vertices), 3)
  )
  around.setAttribute(
    'color',
    new THREE.BufferAttribute(new Float32Array(colors), 3)
  )
  const textures = new THREE.TextureLoader().load(gradient)
  const aroundMaterial = new THREE.PointsMaterial({
    size: 2,
    sizeAttenuation: true, // 尺寸衰减
    color: 0x4d76cf,
    transparent: true,
    opacity: 1,
    map: textures,
  })
  const aroundPoints = new THREE.Points(around, aroundMaterial)
  aroundPoints.name = '星空'
  aroundPoints.scale.set(1, 1, 1)
  group.add(aroundPoints)
}

// 地球
const infoBall = () => {
  // 纹理贴图
  let textureLoader = new THREE.TextureLoader()
  textureLoader.load(map_img, function (texture) {
    // 创建球
    let geometry = new THREE.SphereGeometry(radius, 100, 100)
    let material = new THREE.MeshBasicMaterial({
      map: texture, //设置颜色贴图属性值
    })
    //网格模型对象Mesh
    mesh = new THREE.Mesh(geometry, material)
    // 唯一标识
    mesh.name = '地球'
    // 添加到场景中
    group.add(mesh)
    scene.add(group)
  })
}

// 地球外围贴图
const earthAperture = () => {
  // TextureLoader创建一个纹理加载器对象，可以加载图片作为纹理贴图
  let textureLoader = new THREE.TextureLoader()
  let texture = textureLoader.load(glow_img)

  // 创建精灵材质对象SpriteMaterial
  const spriteMaterial = new THREE.SpriteMaterial({
    map: texture, // 设置精灵纹理贴图
    color: 0x4390d1,
    transparent: true, //开启透明
    opacity: 0.7, // 可以通过透明度整体调节光圈
    depthWrite: false, //禁止写入深度缓冲区数据
  })

  // 创建表示地球光圈的精灵模型
  const sprite = new THREE.Sprite(spriteMaterial)
  sprite.scale.set(radius * 3.0, radius * 3.0, 1) //适当缩放精灵
  // sprite.name = '光晕'
  group.add(sprite)
}

// 扫光动画
const uniforms = {
  glowColor: {
    value: new THREE.Color(0x446bff),
  },
  scale: {
    type: 'f',
    value: -1.0,
  },
  bias: {
    type: 'f',
    value: 1.0,
  },
  power: {
    type: 'f',
    value: 3.3,
  },
  time: {
    type: 'f',
    value: 100,
  },
  isHover: {
    value: false,
  },
  map: {
    value: null,
  },
}
const sweepLight = () => {
  const earth_material = new THREE.ShaderMaterial({
    // wireframe: false, // 显示模型线条
    uniforms: uniforms,
    vertexShader: earthVertex,
    fragmentShader: earthFragment,
  })
  earth_material.needsUpdate = true
  earth_material.transparent = true
  const earth_geometry = new THREE.SphereBufferGeometry(radius + 0.1, 50, 50)
  const earth_mesh = new THREE.Mesh(earth_geometry, earth_material)
  group.add(earth_mesh)
}
// 扫光动画函数
const sweepLightFn = () => {
  uniforms.time.value =
    uniforms.time.value < -100 ? 100 : uniforms.time.value - 1
}

// 添加大气层效果
const createEarthAperture = () => {
  const vertexShader = [
    'varying vec3	vVertexWorldPosition;',
    'varying vec3	vVertexNormal;',
    'varying vec4	vFragColor;',
    'void main(){',
    '	vVertexNormal	= normalize(normalMatrix * normal);', //将法线转换到视图坐标系中
    '	vVertexWorldPosition	= (modelMatrix * vec4(position, 1.0)).xyz;', //将顶点转换到世界坐标系中
    '	// set gl_Position',
    '	gl_Position	= projectionMatrix * modelViewMatrix * vec4(position, 1.0);',
    '}',
  ].join('\n')

  //大气层效果
  const AeroSphere = {
    uniforms: {
      coeficient: {
        type: 'f',
        value: 1.0,
      },
      power: {
        type: 'f',
        value: 3,
      },
      glowColor: {
        type: 'c',
        value: new THREE.Color(0x446bff),
      },
    },
    vertexShader: vertexShader,
    fragmentShader: [
      'uniform vec3	glowColor;',
      'uniform float	coeficient;',
      'uniform float	power;',

      'varying vec3	vVertexNormal;',
      'varying vec3	vVertexWorldPosition;',

      'varying vec4	vFragColor;',

      'void main(){',
      '	vec3 worldCameraToVertex = vVertexWorldPosition - cameraPosition;', //世界坐标系中从相机位置到顶点位置的距离
      '	vec3 viewCameraToVertex	= (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;', //视图坐标系中从相机位置到顶点位置的距离
      '	viewCameraToVertex= normalize(viewCameraToVertex);', //规一化
      '	float intensity	= pow(coeficient + dot(vVertexNormal, viewCameraToVertex), power);',
      '	gl_FragColor = vec4(glowColor, intensity);',
      '}',
    ].join('\n'),
  }
  //球体 辉光 大气层
  const material1 = new THREE.ShaderMaterial({
    uniforms: AeroSphere.uniforms,
    vertexShader: AeroSphere.vertexShader,
    fragmentShader: AeroSphere.fragmentShader,
    blending: THREE.NormalBlending,
    transparent: true,
    depthWrite: false,
  })
  const sphere = new THREE.SphereBufferGeometry(radius + 0.3, 50, 50)
  const mesh = new THREE.Mesh(sphere, material1)
  group.add(mesh)
}

// 添加卫星
const circleLineList = []
const createAnimateCircle = () => {
  // 创建 圆环 点
  const list = getCirclePoints({
    radius: radius + 15,
    number: 150, //切割数
    closed: true, // 闭合
  })
  const mat = new THREE.MeshBasicMaterial({
    color: '#0fff',
    transparent: true,
    opacity: 0.2,
    side: THREE.DoubleSide,
  })
  const line = createAnimateLine({
    pointList: list,
    material: mat,
    number: 100,
    radius: 0.1,
  })
  group.add(line)

  // 在clone两条线出来
  const l2 = line.clone()
  l2.scale.set(1.2, 1.2, 1.2)
  l2.rotateZ(Math.PI / 6)
  group.add(l2)

  const l3 = line.clone()
  l3.scale.set(0.8, 0.8, 0.8)
  l3.rotateZ(-Math.PI / 6)
  group.add(l3)

  /**
   * 旋转的球
   */
  const ball = new THREE.Mesh(
    new THREE.SphereBufferGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
      color: '#e0b187', // 745F4D
    })
  )

  const ball2 = new THREE.Mesh(
    new THREE.SphereBufferGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
      color: '#628fbb', // 324A62
    })
  )

  const ball3 = new THREE.Mesh(
    new THREE.SphereBufferGeometry(1, 32, 32),
    new THREE.MeshBasicMaterial({
      color: '#806bdf', //6D5AC4
    })
  )

  circleLineList.push(line, l2, l3)
  ball.name = ball2.name = ball3.name = '卫星'

  for (let i = 0; i < 2; i++) {
    const ball01 = ball.clone()
    // 一根线上总共有几个球，根据数量平均分布一下
    const num = Math.floor(list.length / 2)
    ball01.position.set(
      list[num * (i + 1)][0] * 1,
      list[num * (i + 1)][1] * 1,
      list[num * (i + 1)][2] * 1
    )
    line.add(ball01)

    const ball02 = ball2.clone()
    const num02 = Math.floor(list.length / 2)
    ball02.position.set(
      list[num02 * (i + 1)][0] * 1,
      list[num02 * (i + 1)][1] * 1,
      list[num02 * (i + 1)][2] * 1
    )
    l2.add(ball02)

    const ball03 = ball2.clone()
    const num03 = Math.floor(list.length / 2)
    ball03.position.set(
      list[num03 * (i + 1)][0] * 1,
      list[num03 * (i + 1)][1] * 1,
      list[num03 * (i + 1)][2] * 1
    )
    l3.add(ball03)
  }
}
// 卫星环绕执行函数
const surround = () => {
  circleLineList.forEach((e) => {
    e.rotateY(-0.01)
  })
}

// 地球入场动画
const ballAnimation = () => {
  fov -= 0.6
  if (fov <= 45) {
    data.animationType = false
    camera.position.set(0, 30, -300) // 地球相机起始点
    camera.lookAt(0, 0, 0)
    infoOrbitControls()
  } else {
    camera = new THREE.PerspectiveCamera(
      fov,
      data.mapDom.clientWidth / data.mapDom.clientHeight,
      1,
      1000
    )
    camera.position.set(0, 0, -300) // 地球相机起始点
    camera.lookAt(0, 0, 0)
  }
}

// 地球自动旋转
const ballRotationY = () => {
  data.rotationY = true
  scene.rotation.y += 0.0005
}

// 添加纹理标记点(国家数据坐标)
const infoMark = (item) => {
  let x = 1
  let y = 1
  if (isLogin.value === false) {
    x = 1.5
    y = 1.5
  }
  let cityGeometry = new THREE.PlaneBufferGeometry(x, y) //默认在XOY平面上 光圈大小
  let textureLoader = new THREE.TextureLoader()
  let texture = textureLoader.load(map_wl)
  let cityWaveMaterial = new THREE.MeshBasicMaterial({
    color: item.color,
    map: texture,
    transparent: true,
    opacity: 0,
    side: THREE.DoubleSide,
  })
  let mesh = new THREE.Mesh(cityGeometry, cityWaveMaterial) as any
  const coord = lon2xyz(radius * 1.005, item.lon, item.lat)
  mesh.scale.set(2, 2, 2)
  // 唯一标识
  mesh.name = item.name
  mesh.privateType = 'mark'
  mesh.position.set(coord.x, coord.y, coord.z)
  const coordVec3 = new THREE.Vector3(coord.x, coord.y, coord.z).normalize()
  const meshNormal = new THREE.Vector3(0, 0, 1)
  mesh.quaternion.setFromUnitVectors(meshNormal, coordVec3)
  if (scene.getObjectByName(item.name) === undefined) {
    group.add(mesh)
    //网格模型添加到场景中
    scene.add(group)
    data.meshAnimateType = true
  }
}

// 添加坐标标签(国家数据标签）
const createLabelObj = (item) => {
  const coord = lon2xyz(radius * 1.1, item.lon, item.lat)
  let labelDiv = document.createElement('div') //创建div容器
  labelDiv.className = 'label_name'
  labelDiv.innerHTML = `
    <div class='label_count'>
      <div>
      ${item.name}
      </div>
      <div>
        <span>12万</span>
      </div>
    </div>
  `
  // 给标签设置坐标位置

  let pointLabel = new CSS2DObject(labelDiv)
  pointLabel.name = item.name
  pointLabel.position.set(coord.x, coord.y, coord.z)

  // group.add(pointLabel)
  scene.add(pointLabel)
}

//精灵标签--标签永远面向相机
const createTxt = (position, name, perData) => {
  var texture = new THREE.CanvasTexture(getCanvasFont())
  var fontMesh = new THREE.Sprite(new THREE.SpriteMaterial({ map: texture }))
  fontMesh.name = name
  // 放大
  fontMesh.scale.x = (10 * radius) / 70
  fontMesh.scale.y = (5 * radius) / 70
  // 在原位置各加 2px ,避免文字与地标重叠
  // fontMesh.position.x = position.x > 0 ? position.x + 2 : position.x - 2
  // fontMesh.position.y = position.y > 0 ? position.y + 2 : position.y - 2
  // fontMesh.position.z = position.z > 0 ? position.z + 2 : position.z - 2
  fontMesh.position.copy(position) //原位置
  group.add(fontMesh)

  // canvas生成图片实现文字函数
  function getCanvasFont() {
    let w = (600 * radius) / (radius * 2)
    let h = (300 * radius) / (radius * 2)
    let canvas = document.createElement('canvas')
    let ctx = canvas.getContext('2d')
    canvas.width = w
    canvas.height = h
    //制作矩形
    ctx.fillStyle = '#091f9099'
    ctx.fillRect(0, 0, w, h)
    //设置文字
    ctx.fillStyle = '#00fffc'
    ctx.font = h / 3 + 'px "微软雅黑"'
    ctx.textAlign = 'center'
    ctx.fillText(
      name,
      (w * radius) / (radius * 2),
      (h * radius) / (radius * 2) - 10
    )
    if (isLogin.value !== false) {
      ctx.fillText(
        perData + '万',
        (w * radius) / (radius * 2),
        (h / (radius * 2)) * radius + (h * radius) / (radius * 3)
      )
    }
    return canvas
  }
}

// 创建地标
const createAreaPoint = (areas) => {
  // 循环创建地标，文字标签
  const name = areas.name
  const perData = areas.perData
  const position = lon2xyz(radius + 5, areas.lon, areas.lat)
  // createHexagon(position); // 地标函数
  createTxt(position, name, perData) // 精灵标签函数
  // createTextCanvas(position,name) // 贴图标签函数
}

// 添加飞线
const flyLineArcGroup = new THREE.Group()
const createFlyLine = (data: any[]) => {
  flyLineArcGroup.userData['flyLineArray'] = []
  group.add(flyLineArcGroup)

  data.forEach((cities) => {
    // 飞线终点坐标数据
    // 调用函数flyArc绘制球面上任意两点之间飞线圆弧轨迹
    cities.endArray.forEach((item: { lon: any; lat: any }) => {
      const arcLine = flyArc(
        radius,
        cities.startArray.lon,
        cities.startArray.lat,
        item.lon,
        item.lat,
        {
          color: 0x409eff, // 飞线的颜色
          flyLineColor: 0xffffff, // 飞行线的颜色
          speed: 0.0001, // 拖尾飞线的速度
        }
      )
      // arcLine.name = 'flyLine'
      flyLineArcGroup.add(arcLine) // 飞线插入flyArcGroup中
      flyLineArcGroup.userData['flyLineArray'].push(arcLine.userData['flyLine'])
    })
  })
}
// 飞线动画函数
const flyLine = () => {
  flyLineArcGroup?.userData['flyLineArray']?.forEach(
    (fly: { rotation: { z: number }; flyEndAngle: number }) => {
      fly.rotation.z += 0.004 // 调节飞线速度
      if (fly.rotation.z >= fly.flyEndAngle) fly.rotation.z = 0
    }
  )
}

// 标记点光圈动画
const meshAnimate = () => {
  for (let i = 0; i < group.children.length; i++) {
    if (group.children[i]?.privateType === 'mark') {
      // 添加初始随机数，防止动画同步
      group.children[i].material.opacity += Math.random() * 0.05
      group.children[i].scale.set(
        group.children[i].material.opacity + 7,
        group.children[i].material.opacity + 7,
        group.children[i].material.opacity + 7
      )
      if (group.children[i].scale.x >= 9) {
        group.children[i].material.opacity = 0
      }
    }
  }
}

// 移动相机
const cameraPos = (objList) => {
  if (isLogin.value === false) return
  if (
    objList.isClick != 'true' &&
    (objList.name === '' ||
      objList.name === undefined ||
      objList.name === '卫星' ||
      objList.name === '卫星2' ||
      objList.name === '卫星3' ||
      objList.name === '飞行线')
  ) {
    // 如果什么都没选，就返回，并且开始旋转和关闭弹窗
    frameDivClose()
    rotation()
    return
  }
  frameDivClose()
  let layerObj = scene.getObjectByName(objList.name)
  if (layerObj) {
    scene.rotation.y = 0
    data.rotationY = false
    new TWEEN.Tween({
      x: data.lonlat.x,
      y: data.lonlat.y,
      z: data.lonlat.z,
    })
      .to(
        {
          x: layerObj.position.x * 2.8,
          y: layerObj.position.y * 2.8,
          z: layerObj.position.z * 2.8,
        },
        1500
      )
      .onUpdate(function () {
        camera.position.x = this.x
        camera.position.y = this.y
        camera.position.z = this.z
        camera.lookAt(0, 0, 0)
      })
      // .onComplete(() => {
      //   retrievalLayer(objList.name)
      // })
      .easing(TWEEN.Easing.Sinusoidal.InOut)
      .start()
    data.lonlat = camera.position
    // 弹窗面板赋值
    data.countryName = objList.name
  } else {
    console.log(
      '图层数据已被全部删除，请重新刷新界面，或者重新调用数据初始化方法: this.infoMap ()'
    )
    alert(
      '图层数据已被全部删除，请重新刷新界面，或者重新调用数据初始化方法: this.infoMap ()'
    )
  }
}

// 检索指定的图层
const retrievalLayer = (name) => {
  let layerObj = scene.getObjectByName(name)
  infoDiv(layerObj.position.x, layerObj.position.y, layerObj.position.z)
}

// 鼠标事件（点击标记的点的事件）
const infoMouse = (event) => {
  event.preventDefault()
  const raycaster = new THREE.Raycaster()
  const mouse = new THREE.Vector2()
  // 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
  let getBoundingClientRect = data.mapDom.getBoundingClientRect()
  mouse.x =
    ((event.clientX - getBoundingClientRect.left) / data.mapDom.offsetWidth) *
      2 -
    1
  mouse.y =
    -((event.clientY - getBoundingClientRect.top) / data.mapDom.offsetHeight) *
      2 +
    1
  //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
  raycaster.setFromCamera(mouse, camera)
  // 获取与射线相交的对象数组，其中的元素按照距离排序，越近的越靠前
  let intersects = raycaster.intersectObjects(scene.children)
  // console.log('🚀 ~ file: WorldA.vue:677 ~ infoMouse ~ intersects:', intersects)
  // 点击对象的处理
  for (let i = 0; i < intersects.length; i++) {
    if (
      intersects[i].object.name !== '地球' &&
      intersects[i].object.name !== ''
    ) {
      // 弹窗面板赋值
      data.countryName = intersects[i].object.name
      let objList = {
        name: intersects[i].object.name,
      }
      cameraPos(objList)
      return false
    } else {
      // 开启自动旋转
      data.rotationY = true
      frameDivClose()
    }
  }
}

// 单独数据展示标签
const infoDiv = (pointx, pointy, pointz) => {
  // 坐标转换
  let world_vector = new THREE.Vector3(pointx, pointy, pointz)
  let vector = world_vector.project(camera)
  let halfWidth = data.mapDom.offsetWidth / 2,
    halfHeight = data.mapDom.offsetHeight / 2
  let x = Math.round(vector.x * halfWidth + halfWidth)
  let y = Math.round(-vector.y * halfHeight + halfHeight)
  //创建div容器
  let moonDiv = document.getElementById('layerMain')
  moonDiv.style.display = 'block'
  moonDiv.style.left = x - 150 + 'px'
  moonDiv.style.top = y - 180 + 'px'
}

// 关闭标签
const frameDivClose = () => {
  let divHtml = document.getElementById('layerMain')
  divHtml.style.display = 'none'
}

// 添加光柱
const infoColumn = (item) => {
  const material = new THREE.MeshBasicMaterial({
    color: item.color,
    transparent: true,
    opacity: 0.9,
    side: THREE.DoubleSide,
  })
  const coord = lon2xyz(radius * 1.01, item.lon, item.lat)
  const coordVec3 = new THREE.Vector3(coord.x, coord.y, coord.z).normalize()
  const geometry = new THREE.CylinderGeometry(0.2, 1.1, 10)
  const mesh = new THREE.Mesh(geometry, material) as any
  mesh.name = item.name
  mesh.privateType = 'column'
  mesh.position.set(coord.x, coord.y, coord.z)
  mesh.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), coordVec3)
  group.add(mesh)
  // scene.add(group)
}

// 删除所有标记点
const delAll = () => {
  frameDivClose()
  group.traverse((item: any) => {
    if (item.type === 'Mesh') {
      item.geometry.dispose()
      item.material.dispose()
    }
  })
  scene.remove(group)
  // 删除group中的children
  if (group.children && group.children.length > 0) {
    let i = 0
    for (i; i < group.children.length; i++) {
      group.remove(group.children[i])
    }
  }
}

// 删除指定标记点
const delMark = (item) => {
  frameDivClose()
  let layerObj = scene.getObjectByName(item.name)
  group.remove(layerObj)
}

// 经纬度转坐标
const lon2xyz = (R, longitude, latitude) => {
  const lon = (Number(longitude) + 90) * (Math.PI / 180)
  const lat = Number(latitude) * (Math.PI / 180)
  const x = R * Math.cos(lat) * Math.sin(lon)
  const y = R * Math.sin(lat)
  const z = R * Math.cos(lon) * Math.cos(lat)
  return { x, y, z }
}

// 开启或关闭地球自动旋转
const rotation = () => {
  data.rotationY = !data.rotationY
}

// 暴露方法
defineExpose({
  infoMark,
  cameraPos,
  frameDivClose,
  infoColumn,
  createLabelObj,
  delAll,
  delMark,
  rotation,
  createFlyLine,
  createAreaPoint,
})
</script>

<template>
  <div>
    <div id="layerMain">
      <div>{{ data.countryName }}</div>
      <div class="shape" />
    </div>
    <div ref="mapId" class="mapId" id="mapId" />
  </div>
</template>

<style lang="scss" scoped>
#mapId {
  width: 100vw;
  height: calc(100vh - 75px);
  // width: 500px;
  // height: 500px;
  z-index: 1;
}
#layerMain {
  position: absolute;
  width: 300px;
  height: 160px;
  line-height: 160px;
  text-align: center;
  color: white;
  display: none;
  background-color: rgba(34, 34, 35, 0.6);
  .shape {
    position: absolute;
    margin: auto;
    left: 0;
    right: 0;
    width: 0;
    height: 0;
    bottom: -40px;
    border: 20px solid transparent;
    border-top-color: rgba(34, 34, 35, 0.6);
  }
}
</style>
<style lang="scss">
.label_count {
  background-color: rgba(0, 0, 0, 0.502);
  color: #89c3f4;
  font-size: 12px;
  font-weight: bold;
  font-family: 微软雅黑;
  padding: 5px;
  border-radius: 3px;
  border: 1px solid #1e80ff;
  div {
    margin-bottom: 5px;
  }
}
</style>
